import com.yxwang.common.time.DateSpan
import com.yxwang.common.time.DatetimeUtil

/*
 * <gext:calendar name="calSelectedDate" action="calendar" url="calendar" urlTarget="Content"
selectedYear="2008" selectedMonth="12" selectedDay="1" />
 * Parameters:
 * @selectedYear
 * @selectedMonth
 * @selectedDay
 */
class CalendarTagLib {
		static namespace = "gext"
		Date currentDate = null;
		int selYear = 2008;
		int selMonth = 12;
		int selDay = 5;
		// Action for year and month.
		String action = null;
		// URL for date.
		String url = null;
		String urlTarget = null;
		String urlParamName = null;
		String urlParamValue = null;
		String onSelectionScript = null;

		def calendar = { attr, body ->
				println "-- Start calendar tag --"
				println attr
				//		println "Selected Year and Month: ${selYear} - ${selMonth}"
				// Today is very important day
				Calendar today = Calendar.getInstance()
				int dayOfToday = today.get(Calendar.DAY_OF_MONTH)
				// Get from tag params
				this.selYear = attr.selectedYear?Integer.parseInt(attr.selectedYear):today.get(Calendar.YEAR)
				this.selMonth = attr.selectedMonth?Integer.parseInt(attr.selectedMonth):today.get(Calendar.MONTH) + 1
				this.selDay = attr.selectedDay?Integer.parseInt(attr.selectedDay):dayOfToday
				this.action = attr.action
				this.onSelectionScript = attr.onSelectionScript
				this.url = attr.url
				this.urlTarget = attr.urlTarget

				//		println "selected time: ${selYear} - ${selMonth} - ${selDay}"

				// Get selected date in Calendar
				Calendar currentCal = new GregorianCalendar(selYear, selMonth - 1, selDay);
				//currentCal.setTime(selDate == null ? new Date() : selDate)
				int dayOfCurrent = currentCal.get(Calendar.DAY_OF_MONTH)
				//		println "Selected date by Calendar is: ${currentCal.getTime()}"

				// Get first day of current month.
				Calendar firstDateOfCurMonth = Calendar.getInstance()
				int selMonth = selMonth
				if (selYear != 0) {
						firstDateOfCurMonth.set(Calendar.YEAR, selYear)
				} else {
						selYear = firstDateOfCurMonth.get(Calendar.YEAR)
				}
				if (selMonth != 0) {
						firstDateOfCurMonth.set(Calendar.MONTH, selMonth - 1)
				} else {
						selMonth = firstDateOfCurMonth.get(Calendar.MONTH) + 1;
				}
				firstDateOfCurMonth.set(Calendar.DAY_OF_MONTH, 1)
				firstDateOfCurMonth.set(Calendar.HOUR_OF_DAY, 0)

				// -------------------
				//		System.out.println("doStartTag() begin")

				out << "<!-- ${currentCal.time} -->"
				out << "<TABLE border='1' class='calendar' cellpadding='1' cellspacing='1'>"
				// Header-Year
				out <<"<TR>"
				out <<"  <TD colspan='7' style='padding:0px;border:0px;'>"
				out <<"  <TABLE class='calendar_head' border='0' width='100%' cellpadding='0' cellspacing='0'>"
				out <<"  <TR>"
				out <<"	 <TD class='calendar_header'>"
				this.generateYearAndMonthLink("<", -1, 0, 0)
				out <<"  </TD>"
				out <<"	 <TD class='calendar_header'><B>${selYear}</B></A></TD>" // Current selected year.
				out <<"  <TD class='calendar_header'>"
				this.generateYearAndMonthLink(">", +1, 0, 0)
				out <<"  </TD>" // Next year.
				out <<"  </TR>"
				out <<"  </TABLE>"
				out <<"  </TD>"
				out <<"</TR>"
				// Header-Month
				out << "<TR>"
				out << "  <TD colspan='7' style='padding:0px;border:0px;'>"
				out << "  <TABLE class='calendar_head' border='0' width='100%'  cellpadding='0' cellspacing='0'>"
				out << "  <TR>"
				//Previous Month Link.
				out << "    <TD class='calendar_header' width='33%'>"
				int preMonth = (selMonth - 1)
				generateYearAndMonthLink("<", preMonth>=1?0:-1, preMonth>=1?-1:11, 0)
				out << "    </TD>"
				//Current Month Label.
				out << "    <TD class='calendar_header' width='33%'><B>${selMonth}</B></TD>"
				//Next Month link.
				out << "    <TD class='calendar_header' width='33%' align='right'>"
				int nextMonth = (selMonth + 1)
				generateYearAndMonthLink(">", nextMonth<=12?0:1, nextMonth<=12?1:-11, 0)
				out << "	</TD>"
				out << "  </TR>"
				out << "  </TABLE>"
				out << "  </TD>"
				out << "</TR>"
				// Header Day of Week.
				out << "<TR>"
				out << "  <TD class='calendar_header_dayofweek'>S</TD>"
				out << "  <TD class='calendar_header_dayofweek'>M</TD>"
				out << "  <TD class='calendar_header_dayofweek'>T</TD>"
				out << "  <TD class='calendar_header_dayofweek'>W</TD>"
				out << "  <TD class='calendar_header_dayofweek'>T</TD>"
				out << "  <TD class='calendar_header_dayofweek'>F</TD>"
				out << "  <TD class='calendar_header_dayofweek'>S</TD>"
				out << "</TR>"

				//Get the week by the first day of month.
				DateSpan currentWeekOfCalendar = DatetimeUtil.getCurrentWeek(firstDateOfCurMonth)
				int dayOfWeek = firstDateOfCurMonth.get(Calendar.DAY_OF_WEEK)
				//		println "The day of week for the first date '${firstDateOfCurMonth.getTime()}' is: ${dayOfWeek}"
				int daysOfMonth = firstDateOfCurMonth.getActualMaximum(Calendar.DAY_OF_MONTH)
				//		println "How many days this month: ${daysOfMonth}"
				// Loop for all full weeks.
				int n = 1;
				int rows = this.calculateCalendarRows(dayOfWeek, daysOfMonth)
				for (int i = 0; i < rows; i++) {
						//			println "${currentWeekOfCalendar.toString()}"
						out << "<TR>"
						List<String> dates = currentWeekOfCalendar.getAllDates("d")
						for (int j = 0; j < dates.size(); j++) {
								print "CELL[${i}, ${j}] ${dates.get(j)}"
								// A cell.
								out << "<TD class='"
								int dayOfMonth = n - dayOfWeek;
								//				println "  ${dayOfCurrent}--${dayOfMonth}"
								if (dayOfMonth < 0) {//Prvious month.
										out << "calendar_othermonth"
								} else if (dayOfMonth >= daysOfMonth) {// Next month.
										out << "calendar_othermonth"
								} else if ((dayOfMonth + 1) == dayOfCurrent) {// It is the selected day.
										//					println "  ${selYear}/${selMonth}/${selDay}  ${currentCal.time} "
										if (currentCal.get(Calendar.YEAR) == selYear && currentCal.get(Calendar.MONTH) == (selMonth - 1)) {//This day.
												out << "calendar_thisday"
												print "  ^"
										} else {// Same date but not same year or month.
												out << "calendar_thismonth"
										}
								} else if ((dayOfMonth + 1) == dayOfToday) { // It is Today.
										if (today.get(Calendar.YEAR) == selYear && today.get(Calendar.MONTH) == (selMonth - 1)) {// Today
												out << "calendar_today"
												print "  @"
										} else {// Same date but not same year or month.
												out << "calendar_thismonth"
										}

								} else {//This month
										out << "calendar_thismonth"
								}
								out << "'>"
								if (dayOfMonth >= 0 && dayOfMonth < daysOfMonth) {
										boolean isUrlAvailable = (url != null && !url.equals("") && !url.equals("#"))
										if (isUrlAvailable == false) {
												out << "<SPAN style='cursor:pointer;' onclick='${onSelectionScript}(${selYear},${selMonth},${dates.get(j)})'>"
										} else {
												out << "<SPAN style='cursor:pointer;'><A HREF='${url}?calendarYear=${selYear}&calendarMonth=${selMonth}&calendarDay=${dates.get(j)}' class='calendar'"
												if(urlTarget != null && urlTarget != ''){
														out << "target='${urlTarget}'"
												}
												out << "></SPAN>"
										}
										out << dates.get(j)
										if (isUrlAvailable == false) {
												out <<"</SPAN>"
										} else {
												out <<"</A>"
										}
								}
								out <<"</TD>"
								n++;
								//				println ''
						}
						out << "</TR>"
						currentWeekOfCalendar.moveDates(7)// Move to next week
				}

				out <<"</TABLE>"
				println "-- Calendar tag end --"
		}

		int calculateCalendarRows(int firstDayInWeek, int daysOfMonth){
				int daysExcludeFirstWeek = daysOfMonth
				int ret = 0
				if(firstDayInWeek != 1){
						daysExcludeFirstWeek = daysOfMonth - (7 - firstDayInWeek)
						ret = 1;
				}
				ret += daysExcludeFirstWeek / 7
				ret += daysExcludeFirstWeek % 7 == 0?0:1
				return ret;
		}

		private void generateYearAndMonthLink(String displaying, int yearOffset, int monthOffset, int dateOffset) {
				boolean isActionAvailable = (action != null && !action.equals("") && !action.equals("#"));
				if (isActionAvailable == true) {
						out << "<A HREF='${action}?calendarYear=${selYear + yearOffset}&calendarMonth=${selMonth + monthOffset}' class='calendar'>${displaying}</A>"
				} else {
						out << "<SPAN style='cursor:pointer;' onclick='${onSelectionScript}(${selYear + yearOffset},${selMonth + monthOffset},${selDay + dateOffset})'>${displaying}</SPAN>"
				}
		}
}
